'''
Created on Nov 22, 2011

@author: onetera
'''
version = 0.2 

from PyQt4 import QtCore , QtGui
from lib.papyDB import papyDB , tableInfo
from lib import globalVar
from lib.papyDBTable import *
from shotAssembler_UI import shotAssembler_UI
from insertItem import insertItemDiag
from lib.itemModel import *
from lib.customUI import customUI
import os
import pickle

s_assetID , s_assetName , s_assetVer  , s_assetStatus  , s_assetType  , s_assetDesc = range(6)

class assmTableModel( QtCore.QAbstractTableModel ):    
    def __init__(self):
        super(assmTableModel, self).__init__()
        self.assmAssets = [] 
         
    def __len__(self):
        return len(self.assmAssets)
        
    def rowCount(self, index=QtCore.QModelIndex() ):
        return len( self.assmAssets )
    
    def columnCount(self, index=QtCore.QModelIndex()):
        return 6
        
    def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
        if role == QtCore.Qt.TextAlignmentRole:
            if orientation == QtCore.Qt.Horizontal:
                return QtCore.QVariant(int(QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter))
            return QtCore.QVariant(int(QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter))
        if role != QtCore.Qt.DisplayRole:
            return QtCore.QVariant()
        if orientation == QtCore.Qt.Horizontal:
            if section == s_assetID:
                return QtCore.QVariant("ID")
            elif section == s_assetName:
                return QtCore.QVariant("Name")
            elif section == s_assetStatus:
                return QtCore.QVariant("Status")
            elif section == s_assetVer:
                return QtCore.QVariant("Version")
            elif section == s_assetType:
                return QtCore.QVariant("Type")
#            elif section == s_assetTexture:
#                return QtCore.QVariant("Texture")
#            elif section == s_assetRigging:
#                return QtCore.QVariant("Rigging")
            elif section == s_assetDesc:
                return QtCore.QVariant("Description")            
        return QtCore.QVariant(int(section + 1))
    
    def flags(self, index):
        if not index.isValid():
            return QtCore.Qt.ItemIsEnabled
        return QtCore.Qt.ItemFlags(
                QtCore.QAbstractTableModel.flags(self, index)|
                QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsDragEnabled | 
                QtCore.Qt.ItemIsDropEnabled | QtCore.Qt.ItemIsSelectable
                )
        
    def supportedDropActions(self):        
        return QtCore.Qt.MoveAction
    
    def mimeTypes(self):
        types = QtCore.QStringList() 
        types.append('text/plain') 
        return types 
    
    def mimeData(self, index):
        theRow = ''  
        if index[0].isValid():
            theRows = str( list(set([ x.row() for x in index ])) )            
        mimeData = QtCore.QMimeData(  )
        mimeData.setText( theRows )        
        return mimeData
                
    def data(self, index, role=QtCore.Qt.DisplayRole):
        if (not index.isValid() or
            not (0 <= index.row() < len(self.assmAssets))):
            return QtCore.QVariant()   
        iASSET = self.assmAssets[ index.row() ]
        column = index.column()
        if role == QtCore.Qt.DisplayRole:
            if column == s_assetID:
                return QtCore.QVariant(iASSET.assetID)
            elif column == s_assetName:
                return QtCore.QVariant(iASSET.assetName)
            elif column == s_assetVer:
                if iASSET.assetVersionList != [[]] and str( iASSET.assetVersion ) != '0[]' :                      
                    return QtCore.QVariant(iASSET.assetVersion )
            elif column == s_assetStatus:
                return QtCore.QVariant(iASSET.assetStatus)
            elif column == s_assetType:
                return QtCore.QVariant(iASSET.assetType)
#            elif column == s_assetRigging:
#                return QtCore.QVariant(iASSET.assetRigging)
#            elif column == s_assetTexture:
#                return QtCore.QVariant(iASSET.assetTexture)
            elif column == s_assetDesc:                  
                return QtCore.QVariant(iASSET.assetDesc)
            
        elif role == QtCore.Qt.BackgroundColorRole and column == s_assetVer :            
            if iASSET.assetVersionList != [[]] and str( iASSET.assetVersion ) != '0[]' :            
                result = filter( lambda x : int(iASSET.assetVersion) < x , iASSET.assetVersionList )            
                if len( result ) > 0 :                                      
                    return QtCore.QVariant( QtGui.QColor(QtCore.Qt.gray) )
        return QtCore.QVariant()
    
    def setData(self, index, value, role=QtCore.Qt.EditRole):
        iAsset = self.assmAssets[index.row()]
        column = index.column()         
        if index.isValid() and 0 <= index.row() < len( self.assmAssets ):            
            if column == s_assetVer and role==QtCore.Qt.EditRole :
                iAsset.assetVersion = value.toString()                      
            self.emit(QtCore.SIGNAL("dataChanged(QModelIndex,QModelIndex)"),
                      index, index)
            return True
        return False

    def removeRows(self, position, rows=1, index=QtCore.QModelIndex() ):
        self.beginRemoveRows(QtCore.QModelIndex(), position, position + rows - 1)        
        self.assmAssets = self.assmAssets[:position] + self.assmAssets[position + rows:]            
        self.endRemoveRows()   
        self.dirty = True     
        return True
    
class assetVerDelegate(QtGui.QStyledItemDelegate):
    
    def __init__(self , parent = None ):
        super(assetVerDelegate ,self ).__init__( parent )
        self.parent = parent

    def createEditor(self, parent, option, index):
        if index.column() == s_assetVer:
            theAsset = self.parent.assmTableModel.assmAssets[ index.row() ]
            if theAsset.assetVersionList != [[]] and str( theAsset.assetVersion ) != '0[]' :  
                ver_cb = QtGui.QComboBox( parent )
                theList =theAsset.assetVersionList               
                map(lambda x:ver_cb.addItem( str( x ).zfill(3) ) , theList )
#                ver_cb.setEditable(True)
                return ver_cb    
                                     
    def setModelData(self, editor, model, index):        
        if index.column() == s_assetVer:
            model.setData(index, QtCore.QVariant(editor.currentText())) 

    def setEditorData(self, editor, index):
        text = index.model().data(index, QtCore.Qt.DisplayRole).toString()
        i = editor.findText(text)
        if i == -1:
            i = 0
        editor.setCurrentIndex(i)
          
class assmHistoryModel:
    def __init__(self , pssd ):
        self.prj = pssd[0][1]
        self.seq = pssd[1][1]
        self.shot = pssd[2][1]
        self.dept = pssd[3][1]
        self.prjID = pssd[0][0]
        self.seqID = pssd[1][0]  
        self.shotID = pssd[2][0]
        self.deptID = pssd[3][0]
        self.userName = pssd[4][1]
        self.userID = pssd[4][0]
        self.history = []
        self.historyCB = [] 
        
#    def __init__(self , prj , seq , shot , dept):
#        self.prj = prj
#        self.seq = seq
#        self.shot = shot
#        self.dept = dept
#        self.prjID = PROJECT.search( 'prjID' , prjCodeName = self.prj  )
#        self.seqID = SEQUENCES.search( 'seqID' , prjID = self.prjID , seqName = self.seq )  
#        self.shotID = SHOT.search( 'shotID' , seqID = self.seqID , shotName = self.shot )
#        self.deptID = DEPARTMENT.search( 'deptID' , dept = self.dept )
#        self.history = []
#        self.historyCB = []  
    
    def setHistory(self , query ):        
#        getUserName = lambda x : USER_INFO.search( 'userLogInName' , userID = x ) 
#        print 'setHistory query :',query               
        temp = papyDB.getFetch(  query  )
        if temp == () or temp[0] == ():
                self.history = [[]]
                self.historyCB = [[]]
        result = [ [int( x[0]) ,  x[1]  ] for x in temp ]               
        self.history = result
        self.historyCB = [ self.userName + '_' + str( i+1 ).zfill(3) for i,x in enumerate(result) ]
        self.history.reverse()
        self.historyCB.reverse()
                      
    def getAssmHistory(self):             
        if type( self.shotID ) == type('') or self.shotID == None :             
            return  
        jobID = JOB_INFO.search( 'ID' , shotID = self.shotID )
        if not jobID : 
            return
        theID = JOB_ASSEMBLE.search( 'ID' , jobID = jobID ) 
        if theID == [] : return
        query = 'select userID , assmTableModel from JOB_ASSEMBLE where fID = %(theID)s' % {'theID':theID }
        self.setHistory( query )
        
    
class shotAssembler( shotAssembler_UI , insertItemDiag ):
    def __init__( self , parent=None ):
        QtGui.QMainWindow.__init__( self , parent)
        shotAssembler_UI.__init__( self ) 
        super(shotAssembler , self).__init__(parent)                       
        
        self.appInfo = appInfo( )
        self.userID = USER_INFO.search( 'userID' , userLogInName = os.environ['username'] )
        self.pssd = [ [0,0] , [0,0] , [0,0] , [0,0] , [ self.userID , os.environ['username'] ] ]
        self.toolDataHandler = toolDataHandler( self.__class__.__name__ , self.userID )
        
        
    def showWin(self):             
        self.setUI()    
            
        self.assmTableModel = assmTableModel()

        self.assmProxyModel = QtGui.QSortFilterProxyModel()
        self.assmProxyModel.setSourceModel( self.assmTableModel )
        self.assmProxyModel.setDynamicSortFilter(True)        
    
        self.assm_table.setModel( self.assmProxyModel )
        self.assm_table.setItemDelegate( assetVerDelegate(self) )
        self.assm_table.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
        self.assm_table.setContextMenuPolicy( QtCore.Qt.CustomContextMenu )
        self.assm_table.customContextMenuRequested.connect( self.popup )
        self.assm_table.setSelectionMode( QtGui.QAbstractItemView.ExtendedSelection )
        
        self.assm_table.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
        self.assm_table.setDragDropOverwriteMode(1)
        self.assm_table.dragEnabled()
        self.assm_table.setAcceptDrops(True)
        self.assm_table.setDragEnabled(True)

        self.prj_cb.currentIndexChanged.connect( self.prjCBchange )
        self.seq_cb.currentIndexChanged.connect( self.seqCBchange )
        self.dept_cb.currentIndexChanged.connect( self.deptCBchange )        
        QtCore.QObject.connect( self.shot_cb, QtCore.SIGNAL("currentIndexChanged(QString)"),
                                self.shotCBchange  )
         
        tooldata = self.toolDataHandler.pickelLoads()
        self.move( tooldata.pos[0] , tooldata.pos[1] )
        self.dept_cb.removeItem (self.dept_cb.findText('Comp') )
        
        
        self.prj_cb.setCurrentIndex( tooldata['prjIndex'] )
        self.seq_cb.setCurrentIndex( tooldata['seqIndex'] )
        self.shot_cb.setCurrentIndex( tooldata['shotIndex'] )
        self.dept_cb.setCurrentIndex( tooldata['deptIndex'] )
        self.setPSSDprj()
        self.setPSSDseq()
        self.setPSSDshot()
        self.setPSSDdept()        
                
        self.insertWin_btn.clicked.connect( self.insertItemWin )
        self.assetDelete_btn.clicked.connect( self.doRemoveItem )
        self.itemUP_btn.clicked.connect( self.doItemUp )
        self.itemDW_btn.clicked.connect( self.doItemDown )
        self.assm_btn.clicked.connect( self.doAssemble )
        
        self.assmHistory_cb.currentIndexChanged.connect( self.loadAssmHistory )
        self.assmClearList_btn.clicked.connect( self.clearTable )
        self.assmLog_btn.clicked.connect( self.doSomething )
        self.initialAssmModel() 
        self.initAssmHistory()
        self.assm_table.dropEvent = self.dropEvent  

        QtCore.QObject.connect(self.assm_table, QtCore.SIGNAL("rowsInserted()"), self.selectFocusedItem)

    def dropEvent(self, event):                
        curr =  eval( str(event.mimeData().text() ) )              
        tg = self.assm_table.indexAt( event.pos() ).row()        
                
        currAssets = [ self.assmTableModel.assmAssets[x] for x in curr ]
        tgAsset = self.assmTableModel.assmAssets[tg]
        [ self.assmTableModel.assmAssets.remove(n) for n in currAssets ]
        newtgIndex = self.assmTableModel.assmAssets.index(tgAsset ) + 1
        [ self.assmTableModel.assmAssets.insert(newtgIndex , m) for m in reversed(currAssets) ]
             
        event.setDropAction(QtCore.Qt.MoveAction)        
        event.accept()
        self.initialAssmModel()
        tgIndexes = range( newtgIndex, len(curr)+newtgIndex ) if len( self.assmTableModel ) > len(curr)+newtgIndex \
                    else range(len( self.assmTableModel ) - len(curr) , len( self.assmTableModel ) )
        
        selectionModel = self.assm_table.selectionModel()
        self.assm_table.selectRow( tgIndexes[0] )
        itemSelection = selectionModel.selection()
        for x in tgIndexes:                
            self.assm_table.selectRow( x )               
            itemSelection.merge( selectionModel.selection() ,  QtGui.QItemSelectionModel.Select ) 
        selectionModel.clearSelection()
        selectionModel.select( itemSelection , QtGui.QItemSelectionModel.Select )
                        
    def selectFocusedItem(self):
        self.assm_table.selectRow( self.assmTableModel.assmAssetFocusIndex )

    def setPSSDprj(self):
        prjName = str( self.prj_cb.currentText() )
        prjID = PROJECT.search( 'prjID' , prjCodeName = prjName )
        self.pssd[0] = [ prjID , prjName ]
    
    def setPSSDseq( self ):
        seqName = str( self.seq_cb.currentText() )
        if seqName == '' : return
        seqID = SEQUENCES.search( 'seqID' , seqName = seqName , prjID = self.pssd[0][0] )
        self.pssd[1] = [ seqID , seqName ]
    
    def setPSSDshot( self ):
        shotName = str( self.shot_cb.currentText() )  
        if shotName == '' : return     
        shotID = SHOT.search( 'shotID' , shotName = shotName , seqID =  self.pssd[1][0] )
        self.pssd[2] = [ shotID , shotName ]
    
    def setPSSDdept( self ):
        deptName = str( self.dept_cb.currentText() )
        deptID = DEPARTMENT.search( 'deptID' , deptName = deptName )
        self.pssd[3] = [ deptID , deptID ]
            
    def prjCBchange( self ):
        self.initSeq()
        self.setPSSDprj()
        
    def seqCBchange( self ):
        self.initShot()
        self.setPSSDseq() 
                
    def shotCBchange(self):                
        self.initAssmHistory()
        self.getWindowInfo()
        self.appInfo.setCustomInfo( prjIndex = self.prj_cb.currentIndex() ) 
        self.appInfo.setCustomInfo( seqIndex = self.seq_cb.currentIndex() )     
        self.appInfo.setCustomInfo( shotIndex = self.shot_cb.currentIndex() )
        self.toolDataHandler.setPickelData( self.appInfo ) 
        self.setPSSDshot()
                
    def deptCBchange(self):
        self.initAssmHistory()
        self.getWindowInfo()
        self.appInfo.setCustomInfo( deptIndex = self.dept_cb.currentIndex() )
        self.toolDataHandler.setPickelData( self.appInfo )
        self.setPSSDdept()
        
    def getWindowInfo( self ):
        self.appInfo.pos = [ self.pos().x() ,self.pos().y() ]    
        self.appInfo.size = [ self.geometry().size().width() , self.geometry().size().height() ]        
    
            
    def popup(self ,pos): 
        pos.setY( pos.y()+120)
        pos.setX( pos.x()+50 )    
        menu = QtGui.QMenu()        
        menu.addAction("Move Up" , self.doItemUp )
        menu.addAction("Move Down" , self.doItemDown )
        menu.addSeparator()
        menu.addAction("Delete Asset" , self.doRemoveItem )
        menu.addAction("Delete All" , self.clearTable )
        action = menu.exec_( self.mapToGlobal( pos ) )
       
    def doSomething(self):
        print self.assmTableModel.assmAssets

    def initialAssmModel( self ):             
        self.assmTableModel.reset()
        self.assm_table.resizeColumnsToContents()
        self.assm_table.setColumnWidth(1,200)
    
    def clearTable(self):
        self.assmTableModel.assmAssets = []
        self.assmTableModel.reset()
            
    def initAssmHistory(self):        
        self.assmHistory_cb.clear()           
        self.assmHistoryModel = assmHistoryModel( self.pssd )        
        self.assmHistoryModel.getAssmHistory( )  
        for x in self.assmHistoryModel.historyCB:                       
            self.assmHistory_cb.addItem(x)               
        self.loadAssmHistory()
        
    def loadAssmHistory(self):
        index = self.assmHistory_cb.currentIndex()
        if self.assmHistoryModel.history == [] :
            self.assmHistory_cb.clear()
            self.clearTable()
            return 
        history= self.assmHistoryModel.history[ index ]        
        self.assmTableModel.assmAssets = pickle.loads( str( history[1] )) 
        self.initialAssmModel()
         
    def doAssemble( self ): 
        print self.pssd[0][0] , self.pssd[1][0] , self.pssd[2][0] , self.pssd[3][0] 
        if self.assmTableModel.assmAssets == [] : return        
        dumpModel = pickle.dumps( self.assmTableModel.assmAssets )        
        dept = self.pssd[3][1]
        tableIDnum = JOB_INFO.search( 'ID' , shotID = self.pssd[2][0] )
        if tableIDnum == []:
            self.alertWin('Error', "\nCan't assemble before register \t\nshot information !!\n")
            return        
        JOB_ASSEMBLE.register( self.userID ,tableIDnum , dumpModel )        
        self.toolDataHandler.setPickelData( self.appInfo )
        self.initAssmHistory()                
        print 'Assembled : ' , self.assmTableModel.assmAssets
        
        
    def moveAsset(self , indexes ,push):
        if push > 0 and len( self.assmTableModel ) > indexes[-1] :
            rItem = self.assmTableModel.assmAssets[ indexes[-1]+1 ]
            self.assmTableModel.assmAssets.insert( indexes[0] , rItem)
            self.assmTableModel.assmAssets.pop( indexes[-1]+2 )
        elif push < 0 and indexes[0] != 0 :        
            lItem = self.assmTableModel.assmAssets[ indexes[0]-1 ]
            if lItem == self.assmTableModel.assmAssets [-1] : return
            self.assmTableModel.assmAssets.insert( indexes[-1]+1 , lItem )
            self.assmTableModel.assmAssets.pop( indexes[0]-1 )
        
    def doItemUp(self):         
        if not self.assm_table.selectedIndexes():return
        theIndexes = [ x.row() for x in self.assm_table.selectedIndexes() ]
        if theIndexes[0] == 0 : return
        theRow = self.assm_table.selectedIndexes()         
        self.moveAsset( theIndexes , -1 )
        self.initialAssmModel()        
        for x in theRow:
            if x.row() != 0:
                self.assm_table.selectRow(x.row()-1) 
    
    def doItemDown(self):         
        if not self.assm_table.selectedIndexes():return
        theIndexes = [ x.row() for x in self.assm_table.selectedIndexes() ]        
        if len( self.assmTableModel) ==  theIndexes[-1]+1 : return
        theRow = self.assm_table.selectedIndexes()        
        self.moveAsset( theIndexes, 1 )
        self.initialAssmModel()        
        for x in theRow:
            if x.row() != len( self.assmTableModel  ):
                self.assm_table.selectRow(x.row()+1)
                                  
    def insertItemWin(self):        
        self.theDiag = insertItemDiag(self  )
        self.theDiag.setcbIndex( self.pssd )
        self.theDiag.showDiag()
        self.theDiag.insertItem_btn.clicked.connect( self.doInsertItem )
        self.theDiag.asset_table.doubleClicked.connect( self.doInsertItem )

    def doInsertItem(self ):     
        if not self.theDiag.asset_table.selectedIndexes():return        
        temp = list(set([ x.row() for  x in  self.theDiag.asset_table.selectedIndexes() ]))
        result = [ self.theDiag.insertAssetTableModel.assets[x] for x in temp ]        
        self.assmTableModel.assmAssets +=  result 
        self.initialAssmModel()
        
    def doRemoveItem( self ):
        if not self.assm_table.selectedIndexes():return
        if self.assmTableModel.rowCount() > 0:            
            temp = list(set( [ self.assmTableModel.assmAssets[x.row() ] for x in self.assm_table.selectedIndexes() ] ))
            for y in temp:
                self.assmTableModel.assmAssets.remove( y )               
            self.assmTableModel.reset() 
            self.initialAssmModel()  

    def closeEvent( self , event ) :        
        self.getWindowInfo()
        self.toolDataHandler.setPickelData( self.appInfo )

if __name__ == '__main__':
    import sys    
    app = QtGui.QApplication(sys.argv)
    ui = shotAssembler()       
    ui.showWin()
    app.exec_() 

